package com.info.zhiduoduo.common.utils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Base64;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

public class CaFileUtil {

	/**
	 * 公钥Map Key
	 */
	public static final String PUBLIC_KEY = "publicKey";

	/**
	 * 私钥Map Key
	 */
	public static final String PRIVATE_KEY = "privateKey";

	public static final String UTF_8 = "UTF-8";

	/**
	 * 证书文件的密码
	 */
	public static final String caFilePassword = "111111";

	/**
	 * 通过PFX证书获取RSA公钥和私钥
	 *
	 * @param pfxPath  证书存放路径
	 * @param password 证书密码
	 * @return
	 */
	public static Map<String, String> loadKeyByFile(String pfxPath, String password) throws Exception {
		KeyStore ks = KeyStore.getInstance("PKCS12");
		FileInputStream fis = new FileInputStream(pfxPath);
		char[] nPassword;
		if (password == null || password.trim().equals("")) {
			nPassword = null;
		} else {
			nPassword = password.toCharArray();
		}
		ks.load(fis, nPassword);
		fis.close();
		Enumeration enumas = ks.aliases();
		String keyAlias = null;
		if (enumas.hasMoreElements()) {
			keyAlias = (String) enumas.nextElement();
		}
		PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, nPassword);
		Certificate cert = ks.getCertificate(keyAlias);
		PublicKey pubkey = cert.getPublicKey();
		String publicKey = java.util.Base64.getEncoder().encodeToString(pubkey.getEncoded());
		String privateKey = Base64.getEncoder().encodeToString(prikey.getEncoded());
		Map<String, String> keyMap = new HashMap<>(2);
		keyMap.put(PUBLIC_KEY, publicKey);
		keyMap.put(PRIVATE_KEY, privateKey);
		return keyMap;
	}

	/**
	 * 首先需要通过jdk的keytool生成秘钥库等，需确保机器中安装有jdk
	 * 0.在本代码环境下,执行1命令时,秘钥库的密码和证书的密码须一致，请自行修改路径
	 * 请确保路径下无名为mykeystore.keystore的文件，否则可能会报密码错等
	 * 1.keytool -genkey -alias mykey -keyalg RSA -keystore F:\工作文件\项目文件\ \嘉银\keystore\mykeystore.keystore -keysize 1024 -validity 3650
	 * 2.keytool -export -alias mykey -keystore /Users/eva/bryan/项目文档/ /keystore/mykeystore.keystore -file  /Users/eva/bryan/项目文档/ /keystore/mykey.cer
	 * 3.代码中的秘钥库密码为keystore,请自行修改
	 */
	public static void genPfxFile() {
		// 专门存放keystore文件的秘钥库路径
		String path = "F:\\工作文件\\项目文件\\ \\嘉银\\keystore\\";
		String keyStoreFile = "mykeystore.keystore";
		// 密码：秘钥库的密码和证书的密码须一致
		String passwd = "111111";
		String keyAlias = "mykey";
		String pfxFile = "mykey.pfx";
		String cerFile = "mykey.cer";

		System.out.println("请确保已执行完注释中的两条命令再执行本代码\n\n");
		System.out.println("1.开始生成PFX文件");
		coverToPfx(path + keyStoreFile, passwd, keyAlias, path + pfxFile);
		System.out.println("===============================================================");
		System.out.println("2.开始提取.cer中的公钥字符串");
		String cerStr = getPubStr(path + cerFile);
		System.out.println("从.cer文件中提取的公钥字符串如下:");
		System.out.println(cerStr);
	}

	//1生成pfx文件
	public static void coverToPfx(String keyStoreFile, String passwd, String keyAlias, String pfxFile) {
		try {
			KeyStore inputKeyStore = KeyStore.getInstance("JKS");
			FileInputStream fis = new FileInputStream(keyStoreFile);
			char[] nPassword = null;
			if ((passwd == null) || passwd.trim().equals("")) {
				nPassword = null;
			} else {
				nPassword = passwd.toCharArray();
			}
			inputKeyStore.load(fis, nPassword);
			fis.close();
			KeyStore outputKeyStore = KeyStore.getInstance("PKCS12");
			outputKeyStore.load(null, passwd.toCharArray());

			//            System.out.println("alias=[" + keyAlias + "]");
			if (inputKeyStore.isKeyEntry(keyAlias)) {
				Key key = inputKeyStore.getKey(keyAlias, passwd.toCharArray());
				Certificate[] certChain = inputKeyStore.getCertificateChain(keyAlias);
				outputKeyStore.setKeyEntry(keyAlias, key, passwd.toCharArray(), certChain);
			}

			FileOutputStream out = new FileOutputStream(pfxFile);
			outputKeyStore.store(out, nPassword);
			out.close();
			System.out.println("已生成PFX文件" + pfxFile);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//2获取公钥字符串
	public static String getPubStr(String cerFile) {
		String key = "";
		// 读取证书文件
		try {
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			FileInputStream in = new FileInputStream(cerFile);

			//生成一个证书对象并使用从输入流 inStream 中读取的数据对它进行初始化。
			Certificate c = cf.generateCertificate(in);
			PublicKey publicKey = c.getPublicKey();
			key = Base64.getEncoder().encodeToString(publicKey.getEncoded());
		} catch (CertificateException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return key;
	}

	public static void main(String[] args) throws Exception {

		// genPfxFile();
		// String caFile = "F:\\工作文件\\项目文件\\ \\得仕支付\\正式证书\\信圣公钥.pfx";
		// String caPassword = "days";

		String caFile = "F:\\工作文件\\项目文件\\ \\传化\\xinsheng2.pfx";
		String caPassword = "111111";

		// 获取公私钥
		Map<String, String> map = RSAUtil.loadKeyByPfxFile(caFile, caPassword);

		String privateKey = map.get(PRIVATE_KEY);
		String publicKey = map.get(PUBLIC_KEY);

		System.out.println("私钥=" + privateKey);
		System.out.println("公钥=" + publicKey);

		String content = "orderNo=45275427654927&originalRequestId=148085116478996480&productDesc=商品描述中文测试";

		System.out.println("加解密：");
		String encrypt = RSAUtil.encrypt(content, publicKey);
		System.out.println("encrypt:" + encrypt);
		String decrypt = RSAUtil.decrypt(encrypt, caFile, caPassword);
		System.out.println("decrypt:" + decrypt);
	}
}
